#include "PlanetDelTask.hh"
#include "XmlServerThread.hh"
#include "../World/Planet.hh"
#include "../Exception.hh"

using namespace Network;
using namespace World;

struct StarIdInvalid {
    void operator () () {
        throw NonFatalProtocolError("game.planet_del_task.star_id invalid");
    }
};

struct PlanetIdInvalid {
    void operator () () {
        throw NonFatalProtocolError("game.planet_del_task.planet_id invalid");
    }
};

struct TaskIdxInvalid {
    void operator () () {
        throw NonFatalProtocolError("game.planet_del_task.task_idx invalid");
    }
};

spPlanetDelTask PlanetDelTask::construct(QDomElement const& message) {
    QDomElement const starIdElem = message.firstChildElement("star_id");
    QDomElement const planetIdElem = message.firstChildElement("planet_id");
    QDomElement const taskIdxElem = message.firstChildElement("task_idx");
    u8 const starId = ::parse_num< u8, StarIdInvalid >(starIdElem);
    u8 const planetId = ::parse_num< u8, PlanetIdInvalid >(planetIdElem);
    u8 const taskIdx = ::parse_num< u8, TaskIdxInvalid >(taskIdxElem);
    return spPlanetDelTask(new PlanetDelTask(starId, planetId, taskIdx));
}

PlanetDelTask::PlanetDelTask(u8 starId, u8 planetId, u8 taskIdx):
    starId(starId),
    planetId(planetId),
    taskIdx(taskIdx) {}

QDomDocument PlanetDelTask::to_xml() const {
    QDomDocument doc;
    QDomElement gameElem = doc.createElement("game");
    QDomElement planetDelTaskElem = doc.createElement("planet_del_task");
    doc.appendChild(gameElem);
    gameElem.appendChild(planetDelTaskElem);
    ::to_xml(planetDelTaskElem, "star_id",   starId);
    ::to_xml(planetDelTaskElem, "planet_id", planetId);
    ::to_xml(planetDelTaskElem, "task_idx",  taskIdx);
    return doc;
}

void PlanetDelTask::process_on_server(XmlServerThread& thread) {
    if (thread.get_state() != GAME)
        throw NonFatalProtocolError("game.planet_del_task unexpected");

    spGalaxy galaxy = thread.get_player()->get_galaxy();
    spStar star = galaxy->get_star(starId);
    spPlanet planet = star->get_planet(planetId);
    planet->del_task(taskIdx);
}
